<?php

declare(strict_types=1);
namespace App\Service\AppService;
use App\Service\BaseService;
use Hyperf\Task\Annotation\Task;

/**
 * @author chenshubo
 * 限流算法令牌桶
 */
class RateLimitService extends BaseService
{
    const RATE_LIMIT_CACHE_KEY = 'rate_limit_event_id_';
    
    /**
     * 获取限流结果
     * @Task
     * @param string $event_id
     * @param int $limitNum
     * @param int $expire
     * @return boolean
     */
    public function getIsRateLimit(string $event_id = null)
    {
        $key = self::RATE_LIMIT_CACHE_KEY . $event_id;
        $nowtime = time();
        $redis = redis();
        $redis->watch($key);
        $limitVal = $redis->get($key);
        
        //获取系统限流配置
        $sysconfig = SystemCacheConfigService::instance()->getCacheInfoBySystemCode('channel_task_user_limit');
        //系统限流极限数量        
        $limitNum = $sysconfig['MicroApiRateLimitNum'] ?? 1000;
        //系统限流时间范围
        $expire   = $sysconfig['MicroRateLimitExpire'] ?? 60;
        
        
        if ($limitVal) {
            $limitVal = json_decode($limitVal, true);
            $limitNumMax = ($limitVal['num']) + (int)(($limitNum / $expire) * ($nowtime - $limitVal['time']));
            $num = min($limitNum, $limitNumMax);
            if ($num <= 0) {
                return false;
            }
        } else {
            $num = $limitNum;
        }
        
        $redisVal = json_encode(['num' => $num - 1, 'time' => $nowtime]);
        $redis->multi();
        $redis->set($key,$redisVal);
        $redis->expire($key,$expire);
        $robResult = $redis->exec();
        if (!$robResult) {
            return false;
        }
        return true;
    }
}